package com.xsp.mybatisxmlsqlparser.multidatabase;

import cn.hutool.core.util.StrUtil;
import lombok.Data;

@Data
public class PostgreSqlDbCharacteristics implements DbCharacteristics {

    private String defaultSchema = "public";

    public PostgreSqlDbCharacteristics() {
    }

    public PostgreSqlDbCharacteristics(String defaultSchema) {
        if (StrUtil.isNotBlank(defaultSchema)) {
            this.defaultSchema = defaultSchema;
        }
    }

    @Override
    public String getColumnMark() {
        return "\"";
    }

    @Override
    public String getDefaultSchema() {
        return defaultSchema;
    }

    @Override
    public DataBasesTypeEnum getDbType() {
        return DataBasesTypeEnum.MYSQL;
    }

    @Override
    public String sysdate() {
        return "now()";
    }

    public String nvl(String a, String b) {
        return String.format("ifnull(%s,%s)", a, b);
    }

    @Override
    public String nvlAlias(String s, String a) {
        return nvlAlias(s, a, s);
    }

    @Override
    public String nvlAlias(String s, String a, String alias) {
        return StrUtil.format("{} as {}", nvl(s, a), alias);
    }

    @Override
    public String nvl2(String s, String a, String b) {
        return String.format("if(isnull(%s),%s,%s)", s, a, b);
    }

    @Override
    public String substr(String a, int b, int c) {
        return String.format("substring(%s,%d,%d)", a, b, c);
    }

    @Override
    public String toChar(String str, String format) {
        return StrUtil.format("date_format({},'{}')", str, convJavaDateTimeFormatToDb(format));
    }

    @Override
    public String toDate(String str, String format) {
        return StrUtil.format("str_to_date({},'{}')", str, convJavaDateTimeFormatToDb(format));
    }

    @Override
    public String toNumber(String str) {
        return String.format("cast(%s as UNSIGNED INTEGER)", str);
    }

    @Override
    public String listagg(String str) {
        return String.format("group_concat(%s)", str);
    }

    @Override
    public String sysGuid() {
        return "md5(uuid())";
    }

    /**
     * 按日加减日期
     *
     * @param field 字段名 字段对应的数据类型为date
     * @param days  正数为后移，负数前移
     * @return
     */
    @Override
    public String plusDays(String field, int days) {
        return StrUtil.format("ADDDATE({},interval {} day)", field, days);
    }

    /**
     * 按日加减日期
     * <p>
     * 用于字符类型的字段，仅支持 yyyy-MM-dd格式的日期
     *
     * @param field 字段名或 文本日期，文本日期需要加单引号括住日期。 如A001044 或 '2001-01-01'
     * @param days  正数为后移，负数前移
     * @return
     */
    @Override
    public String plusDaysForVarchar(String field, int days) {
        return StrUtil.format("DATE_FORMAT(ADDDATE(DATE_FORMAT({},'%Y-%m-%d'), interval {} day),'%Y-%m-%d')", field, days);
    }

    /**
     * 按月加减日期
     *
     * @param field  字段名 字段对应的数据类型为date
     * @param months 正数为后移月份，负数前移
     * @return
     */
    @Override
    public String plusMonths(String field, int months) {
        return StrUtil.format("adddate({},interval {} month)", field, months);
    }

    /**
     * 按月加减日期
     * 正数为后移月份，负数前移
     * 用于字符类型的字段，format为类型
     *
     * @param field  字段名或 文本日期，文本日期需要加单引号括住日期。
     * @param months 正数为后移月份，负数前移
     * @param format 日期格式，使用java的日期格式，内部转换为不同数据库的格式化表达式  支持yyyy-MM-dd 或 yyyy-MM 两种日期格式
     * @return
     */
    @Override
    public String plusMonthsForVarcher(String field, int months, String format) {
        return StrUtil.format("DATE_FORMAT(ADDDATE(DATE_FORMAT({},'{}'), interval {} day),'{}')", field, convJavaDateTimeFormatToDb(format), months, convJavaDateTimeFormatToDb(format));
    }

    /**
     * 计算两个日期差
     *
     * @param field1
     * @param field2
     * @param format 日期格式，使用java的日期格式，内部转换为不同数据库的格式化表达式
     * @return 返回 用于计算field1-field2的结果的sql字符串  field1>field2时 实际运算结果为正数
     */
    @Override
    public String daysForVarcher(String field1, String field2, String format) {
        return StrUtil.format("DATEDIFF(DATE_FORMAT({},'{}'),DATE_FORMAT({},'{}'))", field1, convJavaDateTimeFormatToDb(format), field2, convJavaDateTimeFormatToDb(format));
    }

    /**
     * 转换java的日期时间类型到 对应的数据库的日期类型内
     *
     * @param javaDateTimeFormat
     * @return
     */
    @Override
    public String convJavaDateTimeFormatToDb(String javaDateTimeFormat) {
        // yyyy-MM-dd
        String db = javaDateTimeFormat;
        db = db.replaceAll("yyyy", "%Y");
        db = db.replaceAll("MM", "%m");
        db = db.replaceAll("dd", "%d");
        db = db.replaceAll("HH", "%H");
        db = db.replaceAll("mm", "%i");
        db = db.replaceAll("ss", "%s");

        return String.format("%s", db);
    }

}
